package com.wanmait.wanmarecruit.shiro;

import com.wanmait.wanmarecruit.entity.ManagePermission;
import com.wanmait.wanmarecruit.entity.ManageRole;
import com.wanmait.wanmarecruit.entity.Manager;
import com.wanmait.wanmarecruit.service.ManagePermissionService;
import com.wanmait.wanmarecruit.service.ManageRoleService;
import com.wanmait.wanmarecruit.util.JWTUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Component
public class ManageShiroRealm extends AuthorizingRealm {
    @Resource
    private ManageRoleService manageRoleService;
    @Resource
    private ManagePermissionService managePermissionService;
    @Resource
    private RedisTemplate<String, Manager> redisTemplate;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Manager manager = (Manager) principalCollection.getPrimaryPrincipal();
        List<ManageRole> roles = manageRoleService.findListByManagerId(manager.getId());
        if (roles.isEmpty())
        {
            return null;
        }
        Set<String> roleSet = roles.stream().map(manageRole -> manageRole.getRole()).collect(Collectors.toSet());
        List<Integer> roleIds = roles.stream().map(manageRole -> manageRole.getId()).collect(Collectors.toList());
        List<ManagePermission> managePermissions = managePermissionService.findAllByRoleIds(roleIds);
        Set<String> permissionSet = managePermissions.stream().map(managePermission -> managePermission.getPerm()).collect(Collectors.toSet());
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(roleSet);
        authorizationInfo.setStringPermissions(permissionSet);
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        BearerToken bearerToken = (BearerToken) authenticationToken;
        String token = bearerToken.getToken();
        Manager manager = (Manager) redisTemplate.opsForValue().get(token);
        if (manager==null)
        {
            throw new AuthenticationException("token解析失败");
        }
        if (!JWTUtils.verifyToken(token,manager.getPass()))
        {
            throw new AuthenticationException("token验证失败");
        }

        return new SimpleAuthenticationInfo(manager,token,this.getName());
    }

    //如果使用自定义AuthenticationToken或者BearerToken需要重写下面的方法，否则抛异常UnsupportedTokenException
    @Override
    public boolean supports(AuthenticationToken token) {
        //return token instanceof ShiroToken;
        return token instanceof BearerToken;
    }
}
